﻿using System.Collections.Generic;
using System.Linq;
using HHPS.CreditEducation.DataProvider;
using HHPS.CreditEducation.Frameworks.Commons;
using HHPS.CreditEducation.Frameworks.Constants;

namespace HHPS.CreditEducation.Business
{
    public partial class Business
    {
        #region -- Get Major --

        public List<Major> GetListMajor()
        {
            return DataContex != null ? DataContex.Majors.ToList() : null;
        }

        /// <summary>
        ///  This function shows list of majors in facutly.
        /// </summary>
        /// <param name="idFaculty"> Id of facutly</param>
        /// <returns></returns>
        public List<Major> GetListMajorByIdFaculty(int idFaculty)
        {
            return DataContex != null && idFaculty > 0
                       ? DataContex.Majors.Where(m => m.IdFaculty == idFaculty).ToList()
                       : null;
        }

        #endregion

        #region Common

        private bool MajorCommonValidator(Major major, out string message)
        {
            if (string.IsNullOrWhiteSpace(major.Name))
            {
                message = string.Format(ConstantMessages.RequireFieldIsBlank, "tên Ngành");
                return false;
            }

            if (major.Name.Length >= 50)
            {
                message = string.Format(ConstantMessages.FieldDataOverMaxLength, "tên Ngành", 50);
                return false;
            }

            if (major.IdFaculty == 0 || !DataContex.Faculties.Any(f => f.Id == major.IdFaculty))
            {
                message = string.Format(ConstantMessages.CannotCreateWhenParentNotExist, "Ngành", "Khoa");
                return false;
            }

            message = string.Empty;
            return true;
        }


        #endregion

        #region --Add Major--

        /// <summary>
        /// This function checks validate of add a new major into a faculty
        ///     Is Facutly exsit?
        ///     Is new name major same as orther major
        /// </summary>
        /// <param name="major"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool AddNewMajorValidator(Major major, out string message)
        {
            if (!MajorCommonValidator(major, out message)) return false;

            if (DataContex.Majors.Any(m => m.Name.ToLower() == major.Name.ToLower()))
            {
                message = string.Format(ConstantMessages.ItemIsExisted, major.Name);
                return false;
            }

            return true;
        }

        /// <summary>
        /// This function adds new a major in a facutly
        /// </summary>
        /// <param name="major"></param>
        public void AddNewMajor(Major major)
        {
            DataContex.Majors.AddObject(major);
            DataContex.SaveChanges();

            //Add capacity
            var name = major.Name;
            major = DataContex.Majors.Single(m => m.Name == name);
            foreach (var course in DataContex.Courses)
            {
                DataContex.Capacities.AddObject(new Capacity { IdCourse = course.Id, IdMajor = major.Id, MaxCredit = 28, MinCredit = 15});
            }
            DataContex.SaveChanges();
        }

        #endregion

        #region --Edit Major--

        /// <summary>
        /// This fuction check validate of edit a major function 
        /// </summary>
        /// <param name="major"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool EditMajorValidator(Major major, out string message)
        {
            var id = major.Id;
            if (!DataContex.Majors.Any(m => m.Id == id))
            {
                message = ConstantMessages.CanNotIdentifyItem;
                return false;
            }

            if (!MajorCommonValidator(major, out message)) return false;

            if (DataContex.Majors.Any(m => m.Name.ToLower() == major.Name.ToLower() && m.Id != major.Id))
            {
                message = string.Format(ConstantMessages.ItemIsExisted, major.Name);
                return false;
            }

            return true;
        }

        /// <summary>
        /// This fuction edits a major
        /// </summary>
        /// <param name="major"></param>
        public bool EditMajor(Major major)
        {
            var id = major.Id;
            var updateMajor = DataContex.Majors.SingleOrDefault(f => f.Id == id);

            if (updateMajor == null)
                return false;

            updateMajor.Name = major.Name;
            updateMajor.IdFaculty = major.IdFaculty;
            DataContex.SaveChanges();
            return true;
        }

        #endregion

        #region --Delete Major--

        /// <summary>
        /// This fuction checks validate of delete a major fuction
        /// </summary>
        /// <param name="majors"></param>
        /// <param name="message"></param>
        /// <returns></returns>       
        public bool DeleteMajorsValidator(IEnumerable<Major> majors, out string message)
        {
            const string intialize = "Ngành: ";
            var itemsCannotIdentify = (from major in majors let id = major.Id where !DataContex.Majors.Any(m => m.Id == id) select major).Aggregate(intialize, (current, major) => current + (major.Name + ", "));

            if (itemsCannotIdentify != intialize)
            {
                message = string.Format(ConstantMessages.SomeItemsCanNotIdentify, itemsCannotIdentify.TrimEnd(','));
                return false;
            }
       
            message = string.Empty;
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="majors"></param>
        public void DeleteMajors(List<Major> majors)
        {
            for (var i = majors.Count - 1; i >= 0; i--)
            {
                var id = majors[i].Id;
                var deleteMajor = DataContex.Majors.Single(m => m.Id == id);

                //Delete capacity
                var capacities = DataContex.Capacities.Where(c => c.IdMajor == id).ToList();
                for (var j = capacities.Count - 1; j >= 0; j--)
                {
                    var capId = capacities[j].Id;
                    var deleteCapacity = DataContex.Capacities.Single(c => c.Id == capId);
                    DataContex.Capacities.DeleteObject(deleteCapacity);
                }
                DataContex.Majors.DeleteObject(deleteMajor);
            }
            DataContex.SaveChanges();
        }

        #endregion

    }
}